<?php
/**
 * Description:
 *
 * @author      Eden
 * @datetime    2017/3/28 20:45
 * @copyright   WuHan HuQi Technology Co.,Ltd.
 * @url         http://cnhuqi.com
 */

class Account extends WX_Controller
{
    /**
     * @var array 发送时间间隔
     */
    private $conf = array(
        'bind' => array(
            'key' => 'Bind',
            'lifeTime' => 60,
            'saveTime' => 600
        ),
        'resetpw' => array(
            'key' => 'Resetpw',
            'lifeTime' => 60,
            'saveTime' => 600
        )
    );

    protected $error = '';
    private $cacheConfig = [];
    private $key = '';

    /**
     * @throws Exception
     */
    public function __construct()
    {
        parent::__construct();
        $this->load->driver('cache');
    }

    public function getMobile()
    {
        $send['state'] = false;
        $this->load->model('wx/user/User_Model', 'user');
        $res = $this->user->getMobile($this->userid);
        if (empty($res)) {
            $send['error'] = '用户未绑定账号';
        } else {
            $send['state'] = true;
            $send['data'] = $res;
        }
        $this->output->send($send);
    }

    /**
     * 获取验证码
     */
    public function sms()
    {
        $send['state'] = false;
        do {

            $params = $this->input->get();
            $this->_checkParams($params);

            $type = $params['type'];
            $this->cacheConfig = $this->conf[$type];
            $func = "_" . $type;
            if ($this->$func($params['mobile'])) {
                $send['state'] = true;
                break;
            }

            $send['error'] = !empty($this->error) ? $this->error : '验证码发送失败';
        } while(false);
        $this->output->send($send);
    }

    public function doResetpw()
    {
        $send['state'] = false;
        do {

            $mobile = $this->input->post('mobile');
            $code = $this->input->post('code');
            $password = $this->input->post('password');

            if (empty($mobile) || empty($code) || empty($password)) {
                $send['error'] = '参数错误';
                break;
            }

            // 检查 cache 中是否过期
            $this->cacheConfig = $this->conf['resetpw'];
            $this->key = 'WX:Account:' . $this->cacheConfig['key'] . ':' . $mobile;
            if (!$this->_checkInCache($code)) {
                $send['error'] = $this->error;
                break;
            }

            $this->load->model('wx/user/User_Model', 'user');

            $password = encryptPassword($password);
            if (!$this->user->setUserPassword($this->userid, $password)) {
                $send['error'] = '密码设置失败';
                break;
            }

            $send['state'] = true;
        } while(false);
        $this->output->send($send);
    }

    public function doBind()
    {
        $send['state'] = false;
        do {

            $mobile = $this->input->post('mobile');
            $code = $this->input->post('code');
            $type = $this->input->post('type');
            if (empty($mobile) || empty($code) || empty($type)) {
                $send['error'] = '参数错误';
                break;
            }

            // 检查 cache 中是否过期
            $this->cacheConfig = $this->conf[$type];
            $this->key = 'WX:Account:' . $this->cacheConfig['key'] . ':' . $mobile;
            if (!$this->_checkInCache($code)) {
                $send['error'] = $this->error;
                break;
            }

            $this->load->model('wx/user/User_Model', 'user');
            if (!$this->user->bindAccount($mobile, $this->userid)) {
                $send['error'] = '绑定失败';
                break;
            }

            $send['state'] = true;
        } while(false);
        $this->output->send($send);
    }

    private function _checkInCache($code)
    {
        if ($cachedValue = $this->cache->redis->get($this->key)) {
            $lifeTime = $this->cacheConfig['saveTime']; // 600 s
            $cacheTime = $cachedValue['cacheTime'];     // time()
            $nowTime = time();
            if ($nowTime - $cacheTime > $lifeTime) {
                $this->error = '验证码已过期';
                return false;
            }

            $code = $cachedValue['code'];
            if ($code != $code) {
                $this->error = '验证码错误';
                return false;
            }

            return true;
        }
        return false;
    }

    private function _resetpw($mobile)
    {
        // 检查手机号之前有没有出现过
        if (!$this->_checkPhoneExists($mobile)) {
            $this->error = '手机号未注册';
            return false;
        }

        // 检查是否已经发送过验证码
        if (!$this->_checkCache($mobile)) {
            return false;
        }

        if ($this->_sendSms($mobile)) {
            if ($this->_afterSucc($this->key)) {
                return true;
            }
        }
        return false;

    }

    private function _bind($mobile = '')
    {
        // 检查手机号之前有没有出现过
        if ($this->_checkPhoneExists($mobile)) {
            $this->error = '手机号已被注册';
            return false;
        }

        // 检查是否已经发送过验证码
        if (!$this->_checkCache($mobile)) {
            return false;
        }

        if ($this->_sendSms($mobile)) {
            if ($this->_afterSucc($this->key)) {
                return true;
            }
        }
        return false;
    }

    private function _afterSucc($key)
    {
        try {
            return $this->cache->redis->save($key, array(
                'code' => $this->code,
                'lifeTime' => $this->cacheConfig['lifeTime'],
                'cacheTime' => time()
            ), $this->cacheConfig['saveTime']);
        } catch (Exception $e) {
            $this->error = '配置错误';
        }
        return false;
    }

    private function _checkCache($mobile)
    {
        $this->key = 'WX:Account:' . $this->cacheConfig['key'] . ':' . $mobile;
        return $this->_checkRepeat($this->key);
    }

    /**
     * @param $key
     * @return bool
     */
    private function _checkRepeat($key)
    {
        if ($cachedValue = $this->cache->redis->get($key)) {
            $lifeTime = $this->cacheConfig['lifeTime']; // 60 s
            $cacheTime = $cachedValue['cacheTime'];     // time()
            $nowTime = time();
            if ($nowTime - $cacheTime <= $lifeTime) {
                $this->error = '发送频繁';
                return false;
            }
        }
        return true;
    }

    /**
     * 检查用户是否注册
     * @param $phone
     */
    private function _checkPhoneExists($phone)
    {
        $query = $this->db->get_where('user', array('phone' => $phone));
        return $query->row_array();
    }


    /**
     * 验证参数
     * @param $params
     * @return bool
     */
    private function _checkParams($params)
    {
        $send['state'] = false;
        do {

            if (empty($params['mobile']) || !preg_match('/^1[34578]\d{9}$/', $params['mobile'])) {
                $send['error'] = '手机号格式错误';
                break;
            }

            if (empty($params['type']) || !in_array($params['type'], ['bind', 'resetpw'])) {
                $send['error'] = '无效类型';
                break;
            }
            return true;
        } while(false);
        $this->output->send($send);
    }

    /**
     * 发送
     * @param $phone
     * @return bool
     */
    private function _sendSms($phone)
    {
        $this->config->load('sms');
        $sms_config = $this->config->item('sms');
        $this->load->library('util/Util_Sms', array(
            'template' => $sms_config['tpl']['regist']
        ), 'UtilSms');

        $this->code = rand(1000, 9999);
        if ($this->UtilSms->send($phone, array('{code}' => $this->code))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 检查是否绑定
     */
    public function check()
    {
        $this->load->model('wx/user/User_Model', 'user');
        $send['state'] = true;
        $send['data'] = [
            'isBind' => $this->user->checkBind($this->userid)
        ];
        $this->output->send($send);
    }
}
